/*
* Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
* Description: image sender
*/
#ifndef IAMGE_SENDER_H
#define IAMGE_SENDER_H

#include "image_sender_base.h"
#include "util.h"
#include "mdc/cam/camera/cameradecodedmbufserviceinterface_skeleton.h"
using namespace std;
using namespace cv;

using Skeleton = mdc::cam::camera::skeleton::CameraDecodedMbufServiceInterfaceSkeleton;
class ImageSender : public ImageSenderBase<Skeleton>
{
public:
    ImageSender() = default;
    ImageSender(uint32_t id, cv::Size s, std::string dir): ImageSenderBase<Skeleton>(id, s, dir)
    {
        sourceYuvPath = dir;
        if (dir.back() != '/') {
            sourceYuvPath += string("/") += "imageSource.yuv";
        } else {
            sourceYuvPath += "imageSource.yuv";
        }
#ifdef SAVE_SENDER_FILE
        fpYuv = fopen(sourceYuvPath.c_str(), "wb+");
#endif
        sec = chrono::high_resolution_clock::now();
    }

    ~ImageSender() = default;

    bool RegisterSender()
    {
        std::cout << "Begin register normal image sender." << endl;
        auto result = ImageSenderBase<Skeleton>::RegisterSender();
        std::cout << "Finished to register normal image sender." << endl;
        return result;
    }

    void FillImageAndSend(std::string imgPath, uint32_t seq, void *flag) override
    {
        std::string path = dir;
        std::string postfix = comPara.fileType;
        bool isLoop = comPara.loop;
        cout << "dir : " << dir << "\t" << "postfix :" << postfix << endl;
        std::vector<std::string> files;
        int32_t fileCnt = GetFilesBySort(path, files, comPara.fileType);
        if (fileCnt == 0) {
            cout << "PATH:" << path << " has no files!" << endl;
            return;
        }
        do {
            for (auto &file : files) {
                (void)flag;
                if (file.empty()) {
                    std::cerr << "File not exist,or corrupt.path:" << file << std::endl;
                    return;
                }
                if (!ConfigManage::FileExist(file)) {
                    std::cout << file << " file is not exist!" << std::endl;
                    return;
                }
                Mat YUV;
                cv::Mat BGR = imread(file, IMREAD_COLOR);
                try {
                    if (imgSize.width != BGR.cols || imgSize.height != BGR.rows) {
                        cv::resize(BGR, BGR, imgSize);
                    }
                    cvtColor(BGR, YUV, cv::COLOR_BGR2YUV_I420);
                } catch (cv::Exception &e) {
                    cout << e.what() << endl;
                }
                int32_t frameSize = BGR.rows * BGR.cols * 3 / 2;
                unsigned char *pFrame = (unsigned char *)malloc(frameSize);
                if (nullptr == pFrame) {
                    std::cout << "malloc pFrame memory error" << std::endl;
                    return;
                }
                memset(pFrame, 0, frameSize);
                memcpy(pFrame, YUV.data, frameSize);
                auto imagePub = dataSkeleton->cameraDecodedMbufEvent.Allocate();
                imagePub->CameraHeader.FrameId = frameID;
                imagePub->CameraHeader.Seq = seq;
                imagePub->Width = BGR.cols;
                imagePub->Height = BGR.rows;
                imagePub->DataSize = frameSize;
                imagePub->UdpData.assign(pFrame, pFrame + imagePub->DataSize);
#ifdef SAVE_SENDER_FILE
                fwrite(pFrame, 1, imagePub->DataSize, fpYuv);
#endif
                if (comPara.time.empty()) {
                    timeval now;
                    gettimeofday(&now, NULL);
                    imagePub->CameraHeader.Stamp.Sec = now.tv_sec;
                    imagePub->CameraHeader.Stamp.Nsec = now.tv_usec * 1000U;
                } else {
                    time_t timeStamp = ConvertTimeStr2TimeStamp(comPara.time);
                    auto t1 = chrono::high_resolution_clock::now();
                    int64_t duration = (t1 - sec).count() / 1000000000.0;
                    imagePub->CameraHeader.Stamp.Sec = timeStamp + duration;
                    printf("timeStamp=%ld\n", timeStamp + duration);
                }
                dataSkeleton->cameraDecodedMbufEvent.Send(move(imagePub));
                cout << "Begin send image. seq:" << seq << " frameID:" << frameID << " path:" << file << endl;
                if (comPara.frequency != "") {
                    int32_t freq = atoi(comPara.frequency.c_str());
                    int32_t sleepTime = 1000000 / freq;
                    usleep(sleepTime);
                } else {
                    // 30h 1000000微秒
                    usleep(1000000 / 30); // 30hz
                }
            }
        } while (isLoop);
#ifdef SAVE_SENDER_FILE
        fclose(fpYuv);
#endif
    }
private:
    std::string sourceYuvPath { };
    FILE *fpYuv { nullptr };
    chrono::high_resolution_clock::time_point  sec { };//-t used
};
#endif // IAMGE_SENDER_H
